/*
 * Created by Icodeon Ltd.
 * Date: 04/08/2008
 * 
 * Copyright 2008 All Rights Reserved
 * Icodeon Ltd 
 * St Johns Innovation Centre
 * Cowley Road
 * Cambridge 
 * CB4 0WS United Kingdom
 * 
 * Registered in England and Wales No: 5068195
 * Use is subject to license terms.
 */

using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Configuration;

namespace Icodeon.Util
{
    public class IOUtils
    {
        /// <summary>
        /// Utility to  perform the insert of a parameter value into a parameterized string,
        /// using the common ${...} convention.
        /// </summary>
        /// <param name="parameterizedString">String containing ${...}</param>
        /// <param name="parameterValue">Parameter value to be inserted</param>
        /// <returns></returns>
        public string ReplaceParameter(string parameterizedString, string parameterValue)
        {
            int start = parameterizedString.IndexOf("${");
            string startString = parameterizedString.Substring(0, start);

            int end = parameterizedString.IndexOf("}");
            end++;
            string endString = parameterizedString.Substring(end, (parameterizedString.Length - end));
            return new StringBuilder().Append(startString).Append(parameterValue).Append(endString).ToString();
        }

        public DirectoryInfo GetApplicationDirectory()
        {
            string strAppDir = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
            return new DirectoryInfo(strAppDir);
        }

        public string RemoveUrlParameterString(string relativePath)
        {
            if (relativePath.IndexOf("?") != -1)
            {
                relativePath = relativePath.Substring(0, relativePath.IndexOf("?"));
            }
            return relativePath;
        }

        public DirectoryInfo CombineParentAndChildDirectoryNames(DirectoryInfo parentDirectoryInfo, string childDirectoryName)
        {
            return new DirectoryInfo(Path.Combine(parentDirectoryInfo.FullName, childDirectoryName));
        }

        public FileInfo CombineDirectoryNameAndFileName(DirectoryInfo parentDirectoryInfo, string fileName)
        {
            return new FileInfo(Path.Combine(parentDirectoryInfo.FullName, fileName));
        }

        public string GetFileNameWithoutExtension(FileInfo fi)
        {
            return Path.GetFileNameWithoutExtension(fi.Name);
        }

        public void MakeDirectoriesInPath(DirectoryInfo directoryInfo)
        {
            string fullName = directoryInfo.FullName;
            MakeDirectoriesInPath(fullName, false);
        }

        public void MakeDirectoriesInPath(FileInfo fileInfo)
        {
            string fullName = fileInfo.FullName;
            MakeDirectoriesInPath(fullName, true);
        }

        private void MakeDirectoriesInPath(string fullName, bool isFilePath)
        {
            char[] separator = { Path.DirectorySeparatorChar };
            String[] values = fullName.Split(separator);
            int count = values.Length;
            if (isFilePath)
            {
                count = count - 1;
            }
            String temp = values[0];


            for (int i = 1; i < count; i++)
            {
                temp = temp + Path.DirectorySeparatorChar + values[i];
                DirectoryInfo test = new DirectoryInfo(temp);
                if (!test.Exists)
                {
                    Directory.CreateDirectory(test.FullName);
                    //Debug.WriteLine("Created directory: " + test.FullName);
                }
            }
        }

        public static string ReadSetting(string key)
        {
            return ConfigurationSettings.AppSettings[key];
        }

        public static void WriteSetting(string key, string value)
        {
            // load config document for current assembly
            XmlDocument doc = loadConfigDocument();

            // retrieve appSettings node
            XmlNode node = doc.SelectSingleNode("//appSettings");

            if (node == null)
                throw new InvalidOperationException("appSettings section not found in config file.");

            try
            {
                // select the 'add' element that contains the key
                XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='{0}']", key));

                if (elem != null)
                {
                    // add value for key
                    elem.SetAttribute("value", value);
                }
                else
                {
                    // key was not found so create the 'add' element 
                    // and set it's key/value attributes 
                    elem = doc.CreateElement("add");
                    elem.SetAttribute("key", key);
                    elem.SetAttribute("value", value);
                    node.AppendChild(elem);
                }
                doc.Save(getConfigFilePath());
            }
            catch
            {
                throw;
            }
        }

        public static void RemoveSetting(string key)
        {
            // load config document for current assembly
            XmlDocument doc = loadConfigDocument();

            // retrieve appSettings node
            XmlNode node = doc.SelectSingleNode("//appSettings");

            try
            {
                if (node == null)
                    throw new InvalidOperationException("appSettings section not found in config file.");
                else
                {
                    // remove 'add' element with coresponding key
                    node.RemoveChild(node.SelectSingleNode(string.Format("//add[@key='{0}']", key)));
                    doc.Save(getConfigFilePath());
                }
            }
            catch (NullReferenceException e)
            {
                throw new Exception(string.Format("The key {0} does not exist.", key), e);
            }
        }

        private static XmlDocument loadConfigDocument()
        {
            XmlDocument doc = null;
            try
            {
                doc = new XmlDocument();
                doc.Load(getConfigFilePath());
                return doc;
            }
            catch (System.IO.FileNotFoundException e)
            {
                throw new Exception("No configuration file found.", e);
            }
        }

        private static string getConfigFilePath()
        {
            return Assembly.GetExecutingAssembly().Location + ".config";
        }

    }
}
